package pacman.util;

import java.util.ArrayList;
import java.util.LinkedList;

import org.newdawn.slick.geom.Shape;

import pacman.base.Body;

public class Collider {
    public static void testAndAlert(Body subject, Iterable<Body> obstacles) {
		for (Body obstacle : obstacles) {
		    if (!subject.equals(obstacle) && intersecting(subject, obstacle)) {
			subject.onCollision(obstacle);
			obstacle.onCollision(subject);
		    }
		}
    }

    public static void testAndAlert(Body subject, Body obstacle) {
		if (!subject.equals(obstacle) && intersecting(subject, obstacle)) {
		    subject.onCollision(obstacle);
		    obstacle.onCollision(subject);
		}
    }

    public static boolean isColliding(Body subject, Body obstacle) {
		if (!subject.equals(obstacle) && intersecting(subject, obstacle)) {
		    return true;
		} else {
		    return false;
		}
    }

    public static boolean intersecting(Body one, Body two) {
    	return (checkBounds(one, two) && checkPrimitives(one.shape, two.shape));
    }

    private static boolean checkBounds(Body one, Body two) {
		float x = (float) Math.pow(one.getCenterX() - two.getCenterX(), 2);
		float y = (float) Math.pow(one.getCenterY() - two.getCenterY(), 2);
	
		float r1 = one.shape.getBoundingCircleRadius();
		float r2 = two.shape.getBoundingCircleRadius();
		float r = (float) Math.pow(r1 + r2, 2);
	
		return ((x + y) <= r);
    }

    private static boolean checkPrimitives(Shape one, Shape two) {
    	return one.intersects(two);
    }

    public static Body testAndReturn(Body subject, Iterable<Body> obstacles, Body... exceptions) {
		for (Body obstacle : obstacles) {
		    if (!matches(obstacle, exceptions)
			    && intersecting(subject, obstacle)) {
			return obstacle;
		    }
		}
		return null;
    }


    public static Body testAndReturn(Body subject, Iterable<Body> obstacles) {
		for (Body obstacle : obstacles) {
		    if (!subject.equals(obstacle) && intersecting(subject, obstacle)) {
			return obstacle;
		    }
		}
		return null;
    }

    public static ArrayList<Body> testAndReturnBodies(Body subject, Iterable<Body> obstacles) {
		ArrayList<Body> result = new ArrayList<Body>();
		for (Body obstacle : obstacles) {
		    if (!subject.equals(obstacle) && intersecting(subject, obstacle)) {
			result.add(obstacle);
		    }
		}
		return result;
    }

    public static boolean testAndFlag(Body subject, LinkedList<Body> obstacles, Body... exceptions) {
		for (Body obstacle : obstacles) {
		    if (!matches(obstacle, exceptions)
			    && intersecting(subject, obstacle)) {
			return true;
		    }
		}
		return false;
    }

    private static boolean matches(Body subject, Body... obstacles) {
		for (Body obstacle : obstacles) {
		    if (subject.equals(obstacle)) {
			return true;
		    }
		}
		return false;
    }
}
